package com.example.qqviewspringboot.websocket;

import com.example.qqviewspringboot.data.Message;
import com.example.qqviewspringboot.dto.MessageDto;
import com.example.qqviewspringboot.service.MessagePushService;
import com.example.qqviewspringboot.service.UserService;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.CloseStatus;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;
import org.springframework.web.socket.handler.TextWebSocketHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Component
public class MessageWebSocketHandler extends TextWebSocketHandler {

    private final Map<String, WebSocketSession> userSessions = new ConcurrentHashMap<>();  // 存储用户ID和WebSocket会话
    private final MessagePushService messagePushService;  // 消息推送服务

    @Autowired
    private UserService userService;  // 用于获取用户信息

    @Autowired
    public MessageWebSocketHandler(MessagePushService messagePushService) {
        this.messagePushService = messagePushService;
    }

    /**
     * 判断用户是否已连接
     *
     * @param userId 用户ID
     * @return 是否已连接
     */
    public boolean isUserConnected(Long userId) {
        return userSessions.containsKey(userId.toString());
    }

    /**
     * 向用户发送消息
     *
     * @param recipientId 接收者ID
     * @param content     消息内容
     * @throws IOException 发送异常
     */
    public void sendMessageToUser(Long recipientId, String content) throws IOException {
        WebSocketSession session = userSessions.get(recipientId.toString());
        if (session != null && session.isOpen()) {
            session.sendMessage(new TextMessage(content));  // 发送消息
        }
    }

    /**
     * WebSocket连接建立后的处理逻辑
     *
     * @param session WebSocket会话
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionEstablished(WebSocketSession session) throws Exception {
        Object userIdObj = session.getAttributes().get("userId");
        Long userId = null;

        if (userIdObj instanceof Long) {
            userId = (Long) userIdObj;
        } else if (userIdObj instanceof String) {
            try {
                userId = Long.parseLong((String) userIdObj);
            } catch (NumberFormatException e) {
                System.err.println("Invalid userId format: " + userIdObj);
            }
        }

        if (userId != null) {
            String userIdStr = userId.toString();
            userSessions.put(userIdStr, session);
            System.out.println("WebSocket connected for user: " + userIdStr);

            // 检查该用户是否有待推送的消息
            List<Message> pendingMessages = messagePushService.getPendingMessages(userId);
            for (Message message : pendingMessages) {
                // 发送消息
                sendMessageToUser(message.getRecipient().getId(), buildMessageContent(message));
                // 标记为已推送
                message.setReadStatus(Message.ReadStatus.DELIVERED);
                // 保存消息状态
                // messageService.updateMessageStatus(message.getId(), Message.ReadStatus.DELIVERED);
            }
            // 清空待推送消息
            messagePushService.clearPendingMessages(userId);
        } else {
            session.close();  // 如果用户ID缺失，关闭连接
            System.err.println("User ID is missing or invalid, closing connection.");
        }
    }

    /**
     * 处理接收到的消息
     *
     * @param session WebSocket会话
     * @param message 文本消息
     * @throws Exception 异常
     */
    @Override
    public void handleTextMessage(WebSocketSession session, TextMessage message) throws Exception {
        String payload = message.getPayload();
        ObjectMapper objectMapper = new ObjectMapper();
        MessageDto messageDto = objectMapper.readValue(payload, MessageDto.class);

        Long senderId = messageDto.getSenderId();
        Long recipientId = messageDto.getRecipientId();
        String content = messageDto.getContent();
        String mediaType = messageDto.getMediaType();  // 新增字段
        String mediaUrl = messageDto.getMediaUrl();    // 新增字段

        // 创建 Message 对象
        Message msg = new Message();
        msg.setSender(userService.getUserById(senderId));
        msg.setRecipient(userService.getUserById(recipientId));
        msg.setContent(content);
        msg.setTimestamp(LocalDateTime.now());
        msg.setReadStatus(Message.ReadStatus.UNREAD);
        msg.setMediaType(mediaType);
        msg.setMediaUrl(mediaUrl);

        // 将消息保存在待推送消息中
        messagePushService.savePendingMessage(recipientId, msg);

        // 如果接收者在线，消息会直接推送给他们
        if (isUserConnected(recipientId)) {
            sendMessageToUser(recipientId, buildMessageContent(msg));  // 发送消息
            // 更新消息状态为已推送
            msg.setReadStatus(Message.ReadStatus.DELIVERED);
            // 保存消息状态
            // messageService.updateMessageStatus(msg.getId(), Message.ReadStatus.DELIVERED);
        }
    }

    /**
     * WebSocket连接关闭后的处理逻辑
     *
     * @param session WebSocket会话
     * @param status  关闭状态
     * @throws Exception 异常
     */
    @Override
    public void afterConnectionClosed(WebSocketSession session, CloseStatus status) throws Exception {
        Object userIdObj = session.getAttributes().get("userId");
        Long userId = null;

        if (userIdObj instanceof Long) {
            userId = (Long) userIdObj;
        } else if (userIdObj instanceof String) {
            try {
                userId = Long.parseLong((String) userIdObj);
            } catch (NumberFormatException e) {
                System.err.println("Invalid userId format during disconnect: " + userIdObj);
            }
        }

        if (userId != null) {
            String userIdStr = userId.toString();
            userSessions.remove(userIdStr);
            System.out.println("WebSocket disconnected for user: " + userIdStr);
        }
    }

    /**
     * 构建包含媒体信息的消息内容
     *
     * @param message 消息对象
     * @return 构建后的消息内容
     */
    private String buildMessageContent(Message message) {
        StringBuilder messageContent = new StringBuilder();
        if (message.getContent() != null && !message.getContent().isEmpty()) {
            messageContent.append(message.getContent());
        }
        if (message.getMediaUrl() != null && !message.getMediaUrl().isEmpty()) {
            messageContent.append(" [Media] ").append(message.getMediaUrl());
        }
        return messageContent.toString();
    }
}
